﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using Pampa.CRUD.Core;

namespace Pampa.MVC.Fluent.Common
{
    public class AbstractBuilder
    {
        protected string GetId<T, T2>(Expression<Func<T, T2>> property)
        {
            bool isProperty = true;
            string id = GetId(property, out isProperty);

            if(!isProperty)
            {
                EntityManager.AddCalculatedProperty(id, property);
            }

            return id;
        }

        private string GetId(Expression method, out bool isProperty)
        {
            string id = null;
            var lambda = method as LambdaExpression;

            isProperty = true;

            if (lambda == null)
                throw new ArgumentNullException("Invalid expression. " + method.ToString());

            if (lambda.Body.NodeType == ExpressionType.Convert)
            {
                id = GetIdFromBody(((UnaryExpression)lambda.Body).Operand, out isProperty);
            }
            else
            {
                id = GetIdFromBody(lambda.Body, out isProperty);
            }

            if (id == null)
            {
                throw new Exception("Invalid expression. " + method.ToString());
            }

            return id;
        }

        private string GetIdFromBody(Expression body, out bool isProperty)
        {
            if (body.NodeType == ExpressionType.MemberAccess)
            {
                isProperty = true;
                var memberExpr = body as MemberExpression;
                return GetIdFromMemberExpression(memberExpr);
            }
            else if (body.NodeType == ExpressionType.Call)
            {
                isProperty = false;
                var methodExpr = body as MethodCallExpression;
                return methodExpr.Method.Name;
            }
            else
            {
                isProperty = true;
                return null;
            }        
        }

        private string GetIdFromMemberExpression(MemberExpression expression)
        {
            if (expression.Expression is MemberExpression)
            {
                return GetIdFromMemberExpression((MemberExpression)expression.Expression) + "." + expression.Member.Name;
            }
            else
            {
                return expression.Member.Name;
            }
        }
    }
}
